package ini

import (
	"fmt"
	"os"
	"time"
)

type ListenFun func(string)
type Listener interface {
	listen(inifile string)
}

func (listenfun ListenFun) listen(inifile string) {
	listenfun(inifile)
}

func Watch(inifile string, listener func(string)) (Config, error) {
	if _, err := os.Stat(inifile); err != nil {
		return Config{}, &ErrFileNotExists{err.Error()}
	}
	go Listen(inifile, ListenFun(listener))
	return Parse(inifile)
}

func WatchWithOptions(inifile string, listener func(string), timeout int) (Config, error) {
	if _, err := os.Stat(inifile); err != nil {
		return Config{}, &ErrFileNotExists{err.Error()}
	}
	go ListenTimeout(inifile, ListenFun(listener), timeout)
	return Parse(inifile)
}

func Listen(inifile string, listener Listener) error {
	return ListenTimeout(inifile, listener, 5000)
}

func ListenTimeout(inifile string, listener Listener, timeout int) error {
	initInfo, err := os.Stat(inifile)
	if err != nil {
		return &ErrFileNotExists{err.Error()}
	}
	startTime := time.Now()

	for {
		if timeout != 0 && startTime.Add(time.Duration(timeout)*time.Millisecond).Before(time.Now()) {
			return &ErrTimeout{fmt.Sprintf("Listener waits for too long, time %dms has out", timeout)}
		}
		curInfo, err := os.Stat(inifile)
		if err != nil || !initInfo.ModTime().Equal(curInfo.ModTime()) {
			listener.listen(inifile)
			break
		}
	}

	return nil
}
